package com.yejiarong.common.validate;

import com.yejiarong.common.exception.GlobalException;
import com.yejiarong.common.exception.ResponseCode;
import jakarta.validation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author YeJR
 */
public class ValidateUtils {

    /**
     * Validate that the argument condition is true; otherwise throwing an exception with the specified message.
     * This method is useful when validating according to an arbitrary boolean expression, such as validating a primitive number or using your own custom validation expression.
     * @param expression boolean 表达式
     * @param message 异常信息
     */
    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), message);
        }
    }

    /**
     * Validate that the specified argument is not null; otherwise throwing an exception with the specified message.
     * @param object 校验对象
     * @param message 异常信息
     * @param <T> T
     */
    public static <T> void notNull(final T object, final String message) {
        if (object == null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), message);
        }
    }

    /**
     * Validate that the specified argument is null; otherwise throwing an exception with the specified message.
     * @param object 校验对象
     * @param message 异常信息
     * @param <T> T
     */
    public static <T> void isNull(final T object, final String message) {
        if (object != null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), message);
        }
    }

    /**
     * Validate that the specified argument character sequence is neither null, a length of zero (no characters), empty nor whitespace;
     * otherwise throwing an exception with the specified message.
     * @param chars 字符串
     * @param message 异常信息
     * @param <T> T
     */
    public static <T extends CharSequence> void notBlank(final T chars, final String message) {
        notNull(chars, message);
        int strLen = chars.length();
        isTrue(strLen > 0, message);

        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(chars.charAt(i))) {
                return;
            }
        }
        throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), message);
    }

    /**
     *
     * @param collection 集合
     * @param message 异常信息
     */
    public static <T extends Collection<?>> void notEmpty(T collection, String message) {
        notNull(collection, message);
        if (collection.isEmpty()) {
            throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), message);
        }
    }

    /**
     * 实体类参数有效性验证
     * @param t 验证的实体对象
     * @param groups 验证组
     */
    public static <T> void valid(T t, Class<?>... groups) {
        if (t instanceof Collection) {
            CollectionWrapper<T> wrappedObject = new CollectionWrapper<>((Collection) t);
            valid(wrappedObject, groups);
        }
        try (ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory()) {
            Validator validator = validatorFactory.getValidator();
            Set<ConstraintViolation<T>> errors = validator.validate(t, groups);
            if (CollectionUtils.isNotEmpty(errors)) {
                String msg = errors.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("、"));
                throw new GlobalException(ResponseCode.BAD_REQUEST.getCode(), String.format(ResponseCode.BAD_REQUEST.getDefaultMessage(), msg));
            }

        }
    }

    @Data
    @AllArgsConstructor
    static class CollectionWrapper<T> {

        @Valid
        private Collection<T> list;

    }
}
